using System;
using System.Collections.Generic;
using System.Configuration;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;

using System.Windows.Forms;
using Microsoft.TeamFoundation.Proxy;
using Microsoft.TeamFoundation.Client;
using Microsoft.TeamFoundation.Server;
using Microsoft.TeamFoundation.WorkItemTracking.Client;
using Microsoft.TeamFoundation;
using Microsoft.TeamFoundation.VersionControl.Client;
using System.IO;

namespace PackageMaker2008
{
    public partial class Form1 : Form
    {       
        TeamFoundationServer server;
        private VersionControlServer vcs;
        private Workspace workspace;
        string lib = "";
        private string root = "";
        private string[] splitIds;
        string list_content = "";
        int missing_file = 0;
        int change_len = 0;

        public Form1()
        {
            InitializeComponent();
        }

        #region Connect
        private void Connect()
        {
            Log("Connecting to " + server_combo.Text);
            
            server = ServerConnection.ConnectTfs(server_combo.Text);

            if (server != null)
            {
                ICommonStructureService structureService = (ICommonStructureService)server.GetService(typeof(ICommonStructureService));
                ProjectInfo[] projects = structureService.ListAllProjects();
                vcs = (VersionControlServer)server.GetService(typeof(VersionControlServer));

                //foreach (ProjectInfo p in projects)
                //{
                //    project_combo.Items.Add(p.Name);
                //}
                //project_combo.SelectedIndex = 0;

                Workspace[] wss = GetWorkspaces();

                foreach (Workspace ws in wss)
                {
                    works_txt.Items.Add(ws.Name.ToString());
                }

                works_txt.SelectedIndex = 0;

                Log("Successfully Connect to TFS server");

                groupBox1.Enabled = true;
                connect_btn.Enabled = false;
            }
            else
                Log("Problem Connecting TFS Server");         
        }
        #endregion

        #region Get WorkSpaces
        public Workspace[] GetWorkspaces()
        {
            try
            {
                return vcs.QueryWorkspaces(null, vcs.AuthenticatedUser, System.Net.Dns.GetHostName().ToString());
            }
            catch
            {
                throw;
            }
        }
        #endregion

        #region Logger
        public string GetTempPath()
        {
            string path = System.Environment.GetEnvironmentVariable("TEMP");           
            if (!path.EndsWith("\\")) path += "\\";
            if (!File.Exists(path + "PackageMaker2008Log.txt"))
            {
                FileInfo p_log = new FileInfo(path + "PackageMaker2008Log.txt");
                p_log.Create();
                p_log.Attributes = FileAttributes.Normal;
                p_log.Refresh();
            }
            return path;
        }
        public void File_Info(string location)
        {
            FileInfo fileinfo = new FileInfo(location);
            long file_size = (fileinfo.Length / 1024);
            string date = (DateTime.Today.Day.ToString() + "." + DateTime.Today.Month.ToString() + "." + DateTime.Today.Year.ToString());
            if (file_size > 10000)
                File.Move(GetTempPath() + "PackageMaker2008Log.txt", GetTempPath() + "PackageMaker2008Log " + date + ".txt");
        }
        public void Log(string msg)
        {
            File_Info(GetTempPath() + "PackageMaker2008Log.txt");
            lblGeneralInfo.Items.Add("\n" + msg);
            System.IO.StreamWriter sw = System.IO.File.AppendText(
                GetTempPath() + "PackageMaker2008Log.txt");
            try
            {
                string logLine = System.String.Format(
                    "{0:G}: {1}.", System.DateTime.Now, msg);
                sw.WriteLine(logLine);
            }
            finally
            {
                sw.Close();
            }
            lblGeneralInfo.SelectedIndex = lblGeneralInfo.Items.Count - 1;
            lblGeneralInfo.SelectedIndex = -1;
        }

        #endregion

        #region Form Controls

        private void Form1_Load(object sender, EventArgs e)
        {
            try
            {
                GetTempPath();
                foreach (TeamFoundationServer servers in RegisteredServers.GetServers())
                {
                    server_combo.Items.Add(servers);
                }
                server_combo.SelectedIndex = 0;
            }
            catch (Exception ex)
            {
                Log("Cannot find TFS (" + ex.Message + ")"); 
            }
        }

        private void connect_btn_Click(object sender, EventArgs e)
        {
            Connect();
        }
        private void button1_Click(object sender, EventArgs e)
        {
            //root = "$/" + project_combo.Text;
            splitIds = list_content.Split(',');
            GetChangeset();
        }
        private void textBox1_Leave(object sender, EventArgs e)
        {
            try
            {
                list_content = textBox1.Text.Replace(Environment.NewLine, ",");
                string[] intcheck = list_content.Split(',');
                int check;
                for (int i = 0; i < intcheck.Length; i++)
                {
                    if(intcheck[i] != "")
                        check = Convert.ToInt32(intcheck[i]);
                }
                if (list_content.EndsWith(","))
                    list_content = list_content.Substring(0, list_content.Length - 1);
                Log("You chose the following changeset(s): \n" + list_content);
            }
            catch (Exception ex)
            {
                Log("Changeset " + ex.Message);
            }


        }

        private void server_combo_SelectionChangeCommitted(object sender, EventArgs e)
        {
            connect_btn.Enabled = true;
        }

        private void btnBrowse_Click(object sender, EventArgs e)
        {
            string folderName = string.Empty;
            folderBrowserDialog1.RootFolder = Environment.SpecialFolder.DesktopDirectory;
            folderBrowserDialog1.ShowNewFolderButton = true;
            // Show the FolderBrowserDialog.
            DialogResult result = folderBrowserDialog1.ShowDialog();
            if (result == DialogResult.OK)
            {
                folderName = folderBrowserDialog1.SelectedPath;
            }

            //set package path
            tbxPackge.Text = folderName;
            WriteSetting("destination", folderName);
        }

        private void clear_btn_Click(object sender, EventArgs e)
        {
            Log("Form Cleared");
            textBox1.Text = "";
            textBox1.Focus();
            splitIds = null;
        }

        #endregion

        #region  App Config Writer
        private void WriteSetting(string key, string value)
        {
            // Open App.Config of executable
            Configuration config =
                ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);


            // Add an Application Setting.
            config.AppSettings.Settings.Remove(key);
            config.AppSettings.Settings.Add(key, value);

            // Save the configuration file.
            config.Save(ConfigurationSaveMode.Modified);

            // Force a reload of a changed section.
            ConfigurationManager.RefreshSection("appSettings");
        }
        #endregion

        #region Sorting
        private void Sort()
        {         
            int[] SortSplit = new int[splitIds.Length];
            for (int i = 0; i < splitIds.Length; i++)
            {
                SortSplit.SetValue(Convert.ToInt32(splitIds[i]), i);
            }

            Array.Sort(SortSplit);

            for (int ii = 0; ii < SortSplit.Length; ii++)
            {
                splitIds.SetValue(SortSplit[ii].ToString(), ii);
            }
        }
        #endregion

        #region Get Changesets
        public void GetChangeset()
        {    
            int changeSetId;
           
            if (splitIds.Length >= 1 && splitIds[0].ToString() != "")
            {
                Sort();
                foreach (string id in splitIds)
                {
                    if (id != "")
                    {
                        if (!int.TryParse(id, out changeSetId))
                        {
                            continue;
                        }
                        Changeset changeset = vcs.GetChangeset(changeSetId);
                        change_len = changeset.Changes.Length;
                        string filename, serverFile;
                        string du = Environment.UserDomainName + "\\" + Environment.UserName;
                        workspace = vcs.GetWorkspace(works_txt.Text, du);
                        if (workspace == null)
                        {
                            Log("WorkSpace retunrs Null");
                        }
                        DownloadChangesetFiles(changeset);
                    }
                }
                if (missing_file == change_len)
                    Log("Package Done Without Copy Any File!");
                else if (missing_file != 0 && missing_file < change_len)
                    Log("Package Done, But There Were " + missing_file + " Files Missing From " + change_len);
                else
                    Log("Package Complete");
            }
            else
            {
                Log("Changeset Input string was not in a correct format.");
            }

        }
        #endregion

        #region Create Mapping
        private string CreateMapping(string serverFile, string path)
        {
            string[] fragments = serverFile.Split('/');

            for (int i = 3; i < fragments.Length - 1; i++) // Creating the map without the first folder.
            {
                path += "\\" + fragments[i];
                if (!Directory.Exists(path))
                {
                    Log("Create Mapping: " + path);
                    Directory.CreateDirectory(path);
                }
            }
            //add file name
            path += "\\" + fragments[fragments.Length - 1];
            return path;
        }
        #endregion

        #region Download Changeset Files
        private void DownloadChangesetFiles(Changeset changes)
        {
            string filename, serverFile;
            FileInfo file;
            missing_file = 0;

            foreach (Change item in changes.Changes)
            {
                serverFile = item.Item.ServerItem;

                //check if the file is part of a web project
                if (IsWebProject(serverFile))
                {
                    filename = CreateMapping(serverFile, ConfigurationManager.AppSettings["destination"]);

                    Log("Copy " + serverFile + " to " + filename);
                    item.Item.DownloadFile(filename);
                    file = new FileInfo(filename);

                    file.IsReadOnly = true;
                }
                //get the Dll / Exe from the local directory and add it to the lib directory of the destnation folder
                else
                {
                    lib = ConfigurationManager.AppSettings["destination"] + "\\lib";
                    filename = FindLocalLibFile(serverFile);

                    if (filename != string.Empty)
                    {
                        file = new FileInfo(filename);
                        string path = lib + filename.Substring(filename.LastIndexOf('\\'));
                        Log("Copy " + serverFile + " to " + path);
                        if (!Directory.Exists(lib))
                            Directory.CreateDirectory(lib);

                        file.CopyTo(path, true);
                    }
                    else
                    {
                        Log(serverFile + " Cannot Be Found In '" + works_txt.Text + "' Workspace");
                        missing_file++;
                    }
                }
            }
        }
        #endregion

        #region Define File
        private string FindAssembly(string path)
        {
            int index;
            char delimter = '\\';
            string parentDirPath = path;
            while ((parentDirPath.LastIndexOf(delimter)) != -1) // && !parentDirPath.Equals(ConfigurationManager.AppSettings["source"]))
            {
                try
                {
                    if (Directory.Exists(parentDirPath))
                    {
                        string name = parentDirPath.Substring(parentDirPath.LastIndexOf(delimter) + 1);
                        string[] files = Directory.GetFiles(parentDirPath);
                        foreach (string file in files)
                        {
                            if (file.EndsWith(".vbproj") || file.EndsWith(".csproj"))
                            {
                                StreamReader sr = new StreamReader(file);
                                string input = null;
                                while ((input = sr.ReadLine()) != null)
                                {
                                    if (input.Contains("AssemblyName"))
                                    {
                                        return input.Replace("<AssemblyName>", "").Replace("</AssemblyName>", "").Trim();
                                    }
                                }
                                sr.Close();
                            }
                        }
                    }
                    index = parentDirPath.LastIndexOf(delimter);
                    parentDirPath = parentDirPath.Remove(index);
                }
                catch (Exception ex)
                {
                    return "";
                }
            }
            return "";
        }

        private string FindLocalLibFile(string serverFile)
        {
            try
            {
                string localFile = workspace.GetLocalItemForServerItem(serverFile);
                char delimter = '\\';
                string parentDirPath = localFile;
                int inde = parentDirPath.LastIndexOf(delimter);
                string origi_path = parentDirPath = parentDirPath.Remove(inde);
                //string assembly = FindAssembly(parentDirPath);
                int index = 0;
                string searchPattern = @"\bin\Release";

                //search sub directories for the .dll / .exe
                while ((parentDirPath.LastIndexOf(delimter)) != -1) // && !parentDirPath.Equals(ConfigurationManager.AppSettings["source"]))
                {
                    try
                    {                                                
                        string binDirPath = parentDirPath + searchPattern;

                        if (Directory.Exists(binDirPath))
                        {
                            string name = FindAssembly(origi_path);//parentDirPath.Substring(parentDirPath.LastIndexOf(delimter) + 1);
                            string[] files = Directory.GetFiles(binDirPath);
                            foreach (string file in files)
                            {
                                string suf = file.Substring(file.LastIndexOf(delimter) + 1);
                                int lastDot = suf.LastIndexOf('.');
                                if (lastDot != -1)
                                    suf = suf.Remove(lastDot, suf.Length - lastDot);
                                if (suf.Equals(name))
                                    return file;
                            }
                        }
                        index = parentDirPath.LastIndexOf(delimter);
                        parentDirPath = parentDirPath.Remove(index);
                    }
                    catch (Exception ex)
                    {

                        throw new Exception(ex.Message);

                    }

                }
                return string.Empty;
            }
            catch (Exception ex)
            {
                return string.Empty;
                Log("Problem getting Local Item From Server - Check you workspace");
            }
        }

        private bool IsWebProject(string serverFile)
        {
            try
            {
                string webConfig = "Web.config";

                //workspace = vcs.TryGetWorkspace(serverFile);
                string localFile = workspace.GetLocalItemForServerItem(serverFile);
                string parentDirPath = localFile;
                int index;

                while ((index = parentDirPath.LastIndexOf('\\')) != -1 && !parentDirPath.Equals(ConfigurationManager.AppSettings["source"]))
                {
                    parentDirPath = parentDirPath.Remove(index);
                    if (Directory.Exists(parentDirPath))
                    {
                        string[] fileEntries = Directory.GetFiles(parentDirPath);
                        foreach (string file in fileEntries)
                        {
                            if (file.Trim().ToLower().EndsWith(webConfig.ToLower()))
                                return true;
                        }
                    }
                    else
                        return false;

                }
                return false;
            }
            catch (Exception ex)
            { return false; }
        }
        #endregion        
   }
}

